package org.example.security;

import org.example.util.JwtUtil;
import org.example.util.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private RedisTemplate<String, Object> redisTemplate;
    
    private ObjectMapper objectMapper = new ObjectMapper();
    
    public TokenAuthenticationFilter(AuthenticationManager authenticationManager, RedisTemplate<String, Object> redisTemplate) {
        super(authenticationManager);
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse resp, FilterChain chain) 
            throws IOException, ServletException {
        
        UsernamePasswordAuthenticationToken authenticationToken = null;
        try {
            authenticationToken = this.getAuthentication(request);
            if (authenticationToken != null) {
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                super.doFilterInternal(request, resp, chain);
            } else {
                throw new RuntimeException("授权失败");
            }
        } catch (Exception e) {
            resp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            String json = objectMapper.writeValueAsString(R.ok("登陆失败 " + e.getLocalizedMessage()));
            resp.getWriter().write(json);
        }
        
        
    }
    
    
    
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader("token");
        try {
            if (!StringUtils.isEmpty(token)) {

                Claims claims = JwtUtil.getClaims(token);
                Long userId = claims.get("userId", Long.class);
                String userName = claims.get("username", String.class);

                List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(String.valueOf(userId));
                Collection<GrantedAuthority> authorities = new ArrayList<>();
                for(String permissionValue : permissionValueList) {
                    if(StringUtils.isEmpty(permissionValue)) {
                        continue;
                    }
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                    authorities.add(authority);
                }

                if (!StringUtils.isEmpty(userName)) {
                    return new UsernamePasswordAuthenticationToken(userName, token, authorities);
                }
            } 
            
            return null;
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        
    }

    
}
